﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
using DevExpress.XtraTab;
using Loki.Commands;
using Loki.Engine;
using Loki.Utils;

namespace Loki.UI.Win
{
    public class TabbedForm : FormBase
    {
        protected DevExpress.XtraLayout.LayoutControlItem LAI_Tab;
        protected XtraTabControl CTR_Tab;

        public TabbedForm()
        {
            InitializeComponent();
            this.BindingChanged += InitializeBindings;
            this.BindingChanging += ClearViewModelEvents;
        }

        public new IContainerViewModel ViewModel
        {
            get { return (IContainerViewModel)base.ViewModel; }
            set { base.ViewModel = value; }
        }

        private void InitializeComponent()
        {
            this.LAI_Tab = new DevExpress.XtraLayout.LayoutControlItem();
            this.CTR_Tab = new DevExpress.XtraTab.XtraTabControl();
            ((System.ComponentModel.ISupportInitialize)(this.LAY_Root)).BeginInit();
            this.LAY_Root.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.LAG_Root)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.BMA_Main)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.LAI_Tab)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.CTR_Tab)).BeginInit();
            this.SuspendLayout();
            // 
            // LAY_Root
            // 
            this.LAY_Root.Controls.Add(this.CTR_Tab);
            this.LAY_Root.OptionsCustomizationForm.DesignTimeCustomizationFormPositionAndSize = new System.Drawing.Rectangle(350, 354, 250, 350);
            this.LAY_Root.Size = new System.Drawing.Size(755, 415);
            // 
            // LAG_Root
            // 
            this.LAG_Root.Items.AddRange(new DevExpress.XtraLayout.BaseLayoutItem[] {
            this.LAI_Tab});
            this.LAG_Root.Size = new System.Drawing.Size(755, 415);
            // 
            // LAI_Tab
            // 
            this.LAI_Tab.Control = this.CTR_Tab;
            this.LAI_Tab.CustomizationFormText = "LAI_Tab";
            this.LAI_Tab.Location = new System.Drawing.Point(0, 0);
            this.LAI_Tab.Name = "LAI_Tab";
            this.LAI_Tab.Size = new System.Drawing.Size(735, 395);
            this.LAI_Tab.Text = "LAI_Tab";
            this.LAI_Tab.Padding = new DevExpress.XtraLayout.Utils.Padding(0);
            this.LAI_Tab.Spacing = new DevExpress.XtraLayout.Utils.Padding(0);
            this.LAI_Tab.TextSize = new System.Drawing.Size(0, 0);
            this.LAI_Tab.TextToControlDistance = 0;
            this.LAI_Tab.TextVisible = false;
            // 
            // CTR_Tab
            // 
            this.CTR_Tab.Location = new System.Drawing.Point(12, 12);
            this.CTR_Tab.Name = "CTR_Tab";
            this.CTR_Tab.Size = new System.Drawing.Size(731, 391);
            this.CTR_Tab.TabIndex = 4;
            this.CTR_Tab.SelectedPageChanged += new DevExpress.XtraTab.TabPageChangedEventHandler(this.CTR_Tab_SelectedPageChanged);
            this.CTR_Tab.SelectedPageChanging += new DevExpress.XtraTab.TabPageChangingEventHandler(this.CTR_Tab_SelectedPageChanging);
            // 
            // MDITabbedForm
            // 
            this.ClientSize = new System.Drawing.Size(755, 415);
            this.Name = "MDITabbedForm";
            ((System.ComponentModel.ISupportInitialize)(this.LAY_Root)).EndInit();
            this.LAY_Root.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.LAG_Root)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.BMA_Main)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.LAI_Tab)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.CTR_Tab)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        protected override void OnActivated(EventArgs e)
        {
            if (CTR_Tab.SelectedTabPage != null && CTR_Tab.SelectedTabPage.Controls[0] is ViewControlBase)
            {
                DataBinder.ResetBindings();
                ((ViewControlBase)CTR_Tab.SelectedTabPage.Controls[0]).ViewModel.Activate.Execute(null);
            }
            base.OnActivated(e);
        }

        protected override void OnDeactivate(EventArgs e)
        {
            base.OnDeactivate(e);
            if (CTR_Tab.SelectedTabPage != null && CTR_Tab.SelectedTabPage.Controls[0] is ViewControlBase)
            {
                ((ViewControlBase)CTR_Tab.SelectedTabPage.Controls[0]).ViewModel.Desactivate.Execute(null);
            }
        }

        protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, Keys keyData)
        {
            if (keyData == (Keys.Tab | Keys.Control))
            {
                if (CTR_Tab.SelectedTabPageIndex != CTR_Tab.TabPages.Count - 1)
                {
                    CTR_Tab.SelectedTabPageIndex++;
                    return true;
                }
                else
                    return base.ProcessCmdKey(ref msg, keyData);
            }
            else if (keyData == (Keys.Control | Keys.Tab | Keys.Shift))
            {
                if (CTR_Tab.SelectedTabPageIndex != 0)
                {
                    CTR_Tab.SelectedTabPageIndex--;
                    return true;
                }
                else
                    return base.ProcessCmdKey(ref msg, keyData);
            }
            else
                return base.ProcessCmdKey(ref msg, keyData);
        }

        private void CTR_Tab_SelectedPageChanged(object sender, DevExpress.XtraTab.TabPageChangedEventArgs e)
        {
            List<XtraTabPage> l_pages = CTR_Tab.TabPages.Cast<XtraTabPage>().ToList();
            foreach (var item in l_pages)
            {
                if (item.Controls.Count > 0)
                {
                    ViewControlBase L_Base = item.Controls[0] as ViewControlBase;
                    if (L_Base != null && L_Base.ViewModel != null)
                    {
                        if (item == CTR_Tab.SelectedTabPage)
                        {
                            if (!L_Base.ViewModel.IsActive)
                                L_Base.ViewModel.Activate.Execute(null);
                        }
                        else if (L_Base.ViewModel.IsActive)
                            L_Base.ViewModel.Desactivate.Execute(null);
                    }
                }
            }
        }

        private void CTR_Tab_SelectedPageChanging(object sender, DevExpress.XtraTab.TabPageChangingEventArgs e)
        {

        }

        private void InitializeBindings(object sender, EventArgs e)
        {
            CreatePages(ViewModel.SubModels);
            ViewModel.SubModels.CollectionChanged += ViewModels_CollectionChanged;
        }

        protected void ClearViewModelEvents(object sender, EventArgs e)
        {
            if (ViewModel != null)
            {
                ViewModel.SubModels.CollectionChanged -= ViewModels_CollectionChanged;
                RemovePages(ViewModel.SubModels);
            }
        }

        void ViewModels_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null)
            {
                CreatePages(e.NewItems);
            }
            if (e.OldItems != null)
            {
                RemovePages(e.OldItems);
            }
        }

        private void CreatePages(IEnumerable P_Controls)
        {
            foreach (IViewModel L_Model in P_Controls)
            {
                LokiServices.Event.RegisterPropertyChanged(L_Model, x => x.IsActive, this, (c, s, a) => c.ViewModel_ActivatedChanged(s, a));

                ViewControlBase L_Control = ContextHelper.GetView<ViewControlBase>(L_Model);
                XtraTabPage L_Page = new XtraTabPage();
                try
                {
                    L_Page.Controls.Add(L_Control);
                    L_Control.Dock = System.Windows.Forms.DockStyle.Fill;
                    CTR_Tab.TabPages.Add(L_Page);
                    L_Control.ViewModel = L_Model;

                    if (BindNameOnVMState)
                    {
                        DataBinder.OneWay(L_Page, f => f.Text, L_Model, v => v.IsDirty, ConverterHelper.FormName, L_Model.DisplayName);
                    }

                    this.Text = L_Model.DisplayName;

                    L_Model.LoadData();
                }
                catch (Exception L_Ex)
                {
                    L_Control.Dispose();
                    L_Page.Dispose();
                    ApplicationCommands.ERROR.Execute(L_Ex);
                }
            }
        }

        private void RemovePages(IEnumerable P_Controls)
        {
            foreach (IViewModel L_Model in P_Controls)
            {
                LokiServices.Event.UnregisterPropertyChanged(L_Model, x => x.IsActive, this);

                XtraTabPage L_Page = CTR_Tab.TabPages.FirstOrDefault(x => x.Controls.Count > 0
                    && x.Controls[0] is ViewControlBase && ((ViewControlBase)x.Controls[0]).ViewModel == L_Model);
                if (L_Page != null)
                {
                    CTR_Tab.TabPages.Remove(L_Page);
                    L_Model.Dispose();
                    L_Page.Dispose();
                }
            }
        }

        private void ViewModel_ActivatedChanged(object sender, PropertyChangedEventArgs e)
        {
            List<XtraTabPage> l_pages = CTR_Tab.TabPages.Cast<XtraTabPage>().ToList();
            foreach (var item in l_pages)
            {
                if (item.Controls.Count > 0)
                {
                    ViewControlBase L_Base = item.Controls[0] as ViewControlBase;
                    if (L_Base != null && L_Base.ViewModel == sender && L_Base.ViewModel.IsActive)
                    {
                        if (CTR_Tab.SelectedTabPage != item)
                            CTR_Tab.SelectedTabPage = item;
                    }
                }
            }
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            List<XtraTabPage> l_pages = CTR_Tab.TabPages.Cast<XtraTabPage>().Reverse().ToList();
            foreach (var item in l_pages)
            {
                if (item.Controls.Count > 0)
                {
                    ViewControlBase L_Base = item.Controls[0] as ViewControlBase;
                    if (L_Base != null && L_Base.ViewModel.IsDirty && !(L_Base.ViewModel is ISubViewModel))
                    {
                        if (L_Base.ViewModel.IsDirty)
                        {
                            if (MessageBoxes.Confirm(Messages.UIMessages.CONFIRM_EXTERNAL_CLOSE, L_Base.ViewModel.DisplayName))
                            {
                                if (CTR_Tab.SelectedTabPage == item && CTR_Tab.TabPages.Count > 1 && CTR_Tab.TabPages.IndexOf(item) > 0)
                                {
                                    CTR_Tab.SelectedTabPage = CTR_Tab.TabPages[CTR_Tab.TabPages.IndexOf(item) - 1];
                                }
                                L_Base.ViewModel.AcceptChanges();
                            }
                            else
                            {
                                CTR_Tab.SelectedTabPage = item;
                                e.Cancel = true;
                                return;
                            }
                        }
                    }
                }
            }
            base.OnClosing(e);
        }
    }
}
